//
// File:	ParserElement.cpp
// Author:	Thomas TISSOT-DUPONT
// Login:	<thomas.tissotdupont@free.fr>
//
// Create:	02/02/2010 at 09:04:39
// Purpose:	
//
#include <iomanip>
#include "Util.hpp"
#include "Parser.hpp"
#include "Trace.hpp"

//------------------------------------------------------------------
// Constructor / Destructor
//------------------------------------------------------------------
Parser::Element::Element(const std::string &name /* = "" */)
	:	m_name(name),
		m_keyvalues(),
		m_children()
{
	util::tolower(m_name);
}

Parser::Element::~Element()
{
	std::list<Element *>::iterator child_it = m_children.begin();
	std::list<Element *>::iterator child_ite = m_children.end();
	for (; child_it != child_ite; ++child_it)
	{
		delete *child_it;
	}
}

//------------------------------------------------------------------
// Name
//------------------------------------------------------------------
void Parser::Element::SetName(const std::string &name)
{
	m_name = util::tolower(name);
}

const std::string &Parser::Element::GetName() const
{
	return m_name;
}

//------------------------------------------------------------------
// Children
//------------------------------------------------------------------
void Parser::Element::AddChild(Element *pChildElement)
{
	m_children.push_back(pChildElement);
}

const std::list<Parser::Element *> &Parser::Element::GetChildren() const
{
	return m_children;
}

Parser::Element *Parser::Element::FindChild(const std::string &name) const
{
	std::list<Element *>::const_iterator it = GetChildren().begin();
	std::list<Element *>::const_iterator ite = GetChildren().end();
	for (it; it != ite; ++it)
	{
		if (*it && (*it)->GetName() == name)
			return *it;
	}
	return NULL;
}

std::list<const Parser::Element *> Parser::Element::FindChildren(const std::string &name) const
{
	std::list<const Element *> childrenList;
	std::list<Element *>::const_iterator it = GetChildren().begin();
	std::list<Element *>::const_iterator ite = GetChildren().end();
	for (it; it != ite; ++it)
	{
		if (*it && (*it)->GetName() == name)
			childrenList.push_back(*it);
	}
	return childrenList;
}

bool Parser::Element::HasChildren(const std::list<std::string> &names) const
{
	std::list<std::string>::const_iterator it = names.begin();
	std::list<std::string>::const_iterator ite = names.end();
	for (; it != ite; ++it)
	{
		if (FindChild(*it) == NULL)
			return false;
	}
	return true;
}

//------------------------------------------------------------------
// KeyValues
//------------------------------------------------------------------
void Parser::Element::AddKeyValue(const std::string &key, const std::string &value)
{
	m_keyvalues[util::tolower(key)] = Variant(value);
}

const std::map<std::string, Variant> &Parser::Element::GetKeyValues() const
{
	return m_keyvalues;
}

bool Parser::Element::HasKey(const std::string &key) const
{
	return (m_keyvalues.find(util::tolower(key)) != m_keyvalues.end());
}


bool Parser::Element::HasKeys(const std::list<std::string> &keys) const
{
	std::list<std::string>::const_iterator it = keys.begin();
	std::list<std::string>::const_iterator ite = keys.end();
	for (; it != ite; ++it)
	{
		if (HasKey(*it) == false)
			return false;
	}
	return true;
}

//NOTE: this method will return the FIRST matching element
Variant Parser::Element::GetValueForKey(const std::string &key, const Variant &defaultValue /* = Variant() */) const
{
	std::map<std::string, Variant>::const_iterator loc = m_keyvalues.find(util::tolower(key));
	if (loc != m_keyvalues.end())
		return loc->second;
	return defaultValue;
}

//------------------------------------------------------------------
// Dump
//------------------------------------------------------------------
void Parser::Element::Dump(int level /* = 8 */) const
{
	Trace::debug << "------------------------------------------------------------" << std::endl;
	Trace::debug << std::setw(level) << std::fixed << "Block: " << GetName() << std::endl;
	std::map<std::string, Variant>::const_iterator kv_it = GetKeyValues().begin();
	std::map<std::string, Variant>::const_iterator kv_ite = GetKeyValues().end();
	for (; kv_it != kv_ite; ++kv_it)
	{
		Trace::debug << std::setw(level) << std::fixed << "Key:\t" << kv_it->first << std::endl;
		Trace::debug << std::setw(level) << std::fixed << "\t\tToString: " << kv_it->second.ToString() << std::endl;
		Trace::debug << std::setw(level) << std::fixed << "\t\tToFloat: " << kv_it->second.ToFloat() << std::endl;
		Trace::debug << std::setw(level) << std::fixed << "\t\tToInt: " << kv_it->second.ToInt() << std::endl;
		Trace::debug << std::setw(level) << std::fixed << "\t\tToBool: " << std::boolalpha << kv_it->second.ToBool() << std::endl;
	}
	std::list<Element *>::const_iterator child_it = GetChildren().begin();
	std::list<Element *>::const_iterator child_ite = GetChildren().end();
	for (; child_it != child_ite; ++child_it)
	{
		(*child_it)->Dump(level + 8);
	}
}
